package cn.gailvlun.gll.chatkit

import android.graphics.Rect
import android.support.v7.widget.RecyclerView
import android.util.SparseBooleanArray
import android.view.ViewGroup

class StickerLayoutManager : RecyclerView.LayoutManager {
    override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
        return RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT)
    }

    private var emojiColumns: Int
    private var emojiRows: Int
    private var emojiCount: Int // this can't be change, cause emoji is system provided, not user provided
    private var columns: Int
    private var rows: Int

    private var pages = 0

    constructor(emojiColumns: Int, emojiRows: Int, stickEmojiCount: Int, columns: Int, rows: Int) : super() {
        // 表情可能有不同的宽高
        this.emojiColumns = emojiColumns
        this.emojiRows = emojiRows
        this.emojiCount = stickEmojiCount
        this.columns = columns
        this.rows = rows
    }

    override fun canScrollHorizontally(): Boolean {
        return true
    }

    private var mTotalDistance = 0
    private var mMaxDistance = 0

    // 向左滑 dx > 0, 向右滑 dx < 0
    override fun scrollHorizontallyBy(dx: Int, recycler: RecyclerView.Recycler, state: RecyclerView.State): Int {
        var dx = dx
        if (mTotalDistance + dx < 0) {
            dx = -mTotalDistance
        }
        if (mTotalDistance + dx > mMaxDistance) {
            dx = mMaxDistance - mTotalDistance
        }
        mTotalDistance += dx
        offsetChildrenHorizontal(-dx)

//        fill(recycler, state)

        return dx
    }

    private var boundList = ArrayList<Rect>()

    override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {
//        super.onLayoutChildren(recycler, state)
        mRecycler = recycler
        mState = state

        state.itemCount.apply {
            if (this == 0) {
                return
            }
        }

        detachAndScrapAttachedViews(recycler)
//        resetSparseArray()

        fill(recycler, state)
    }

//    private fun resetSparseArray() {
//        sparseArray.clear()
//    }

    private var isFirstLayout = true
    private var containerRect = Rect()
//    private var sparseArray = SparseBooleanArray()

    private fun updateRect() {
        containerRect.set(0, 0, width, height)
        containerRect.offset(mTotalDistance, 0)
    }

    private var mRecycler: RecyclerView.Recycler? = null
    private var mState: RecyclerView.State? = null

    private fun fill(recycler: RecyclerView.Recycler, state: RecyclerView.State) {
        updateRect()

        if (isFirstLayout) {
            isFirstLayout = false

            // <editor-fold desc="找到 emoji view 的长宽，因为 sticker 是第一个，所以直接取第一个">
            val emojiView = recycler.getViewForPosition(0)
            measureChildWithMargins(emojiView, 0, 0)
            val emojiWidth = emojiView.measuredWidth
            val emojiHeight = emojiView.measuredHeight
            // </editor-fold>

            // <editor-fold desc="确定 emoji 页数">
            val emojiPages = emojiCount / (emojiRows * emojiColumns) + 1
            // </editor-fold>

            // <editor-fold desc="确定 sticker 页数">
            val stickerPages = (state.itemCount - emojiCount) / (rows * columns)
            val emojiPagesCount = emojiPages * emojiColumns * emojiRows
            // </editor-fold>

            // <editor-fold desc="找到 sticker 的长宽">
            val stickerView = recycler.getViewForPosition(emojiPagesCount)
            measureChildWithMargins(stickerView, 0, 0)
            val stickerWidth = stickerView.measuredWidth
            val stickerHeight = stickerView.measuredHeight
            // </editor-fold>

            // <editor-fold desc="总页数"
            pages = emojiPages + stickerPages
            // </editor-fold>

            // <editor-fold desc="获取 RecyclerView 的长宽"
            val recyclerViewWidth = width
            val recyclerViewHeight = height
            // </editor-fold>

            // <editor-fold desc="能滑动的最大距离">
            mMaxDistance = (pages - 1) * recyclerViewWidth
            // </editor-fold>

            // <editor-fold desc="emoji 排版"
            for (pos in 0 until emojiPagesCount) {
                // 找到对应的点
                val currPage = pos / (emojiRows * emojiColumns)
                val column = pos % emojiColumns
                val row = pos % (emojiRows * emojiColumns) / emojiColumns

                val verticalEmptySpace = recyclerViewHeight - emojiHeight * emojiRows
                val singleVerticalEmptySpace = verticalEmptySpace / (emojiRows + 1)
                val currTop = singleVerticalEmptySpace * (row + 1) + emojiHeight * row

                val allSpace = recyclerViewWidth - emojiColumns * emojiWidth
                val singleSpace = allSpace / (emojiColumns + 1)
                val left = singleSpace * (column + 1) + emojiWidth * column + recyclerViewWidth * currPage

                val posLeft = left
                val posTop = currTop

                boundList.add(Rect(posLeft, posTop, posLeft + emojiWidth, posTop + emojiHeight))
            }
            // </editor-fold>

            // <editor-fold desc="sticker 排版"
            for (pos in emojiPagesCount until state.itemCount) {
                // 找到对应的点
                val currPage = (pos - emojiPagesCount) / (rows * columns) + emojiPages //
                val column = (pos - emojiPagesCount) % columns
                val row = (pos - emojiPagesCount) % (rows * columns) / columns

                val verticalEmptySpace = recyclerViewHeight - stickerHeight * rows
                val singleVerticalEmptySpace = verticalEmptySpace / (rows + 1)
                val currTop = singleVerticalEmptySpace * (row + 1) + stickerHeight * row

                val allSpace = recyclerViewWidth - columns * stickerWidth
                val singleSpace = allSpace / (columns + 1)
                val left = singleSpace * (column + 1) + stickerWidth * column + recyclerViewWidth * currPage

                val posLeft = left
                val posTop = currTop

                boundList.add(Rect(posLeft, posTop, posLeft + stickerWidth, posTop + stickerHeight))
            }
            // </editor-fold>
        }

//        val count = childCount
//        for (i in count - 1 downTo 0) {
//            val view = getChildAt(i)
//            if (!Rect.intersects(Rect(0, 0, width, height), Rect(view.left, view.top, view.right, view.bottom))) {
//                val position = getPosition(view)
//                sparseArray.put(position, false)
//                removeAndRecycleViewAt(i, recycler)
////                detachAndScrapViewAt(i, recycler)
//            }
//        }

//        Log.d("test", "childCount: $childCount")

        for (pos in 0 until state.itemCount) {
            val bound = Rect(boundList[pos])

//            if (!sparseArray.get(pos)
//                    && Rect.intersects(containerRect, bound)
//            ) {
//                sparseArray.put(pos, true)
//
                bound.offset(-mTotalDistance, 0)

                val indexView = recycler.getViewForPosition(pos)
                addView(indexView, pos)
                measureChildWithMargins(indexView, 0, 0)
//                Log.d("test", "pos: $pos, distance: $mTotalDistance, left: ${bound.left}, right: ${bound.right}")
                layoutDecoratedWithMargins(indexView, bound.left, bound.top, bound.right, bound.bottom)
//            }
        }
    }

    fun scrollToPage(page: Int) {
        val diff = mTotalDistance - width * page
        mTotalDistance = width * page
        offsetChildrenHorizontal(diff)

        fill(mRecycler!!, mState!!)
    }
}